package cn.learn.config;

import cn.learn.properties.TokenProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 令牌存储策略（有五种方式）
 *
 * @author huangyezhan
 * @date 2020年02月28日1:01
 */
@Slf4j
@Configuration
public class TokenConfig {

    @Resource
    private TokenProperties tokenProperties;

    @Bean
    public TokenStore tokenStore() {
        //JWT令牌存储方案
        return new JwtTokenStore(this.accessTokenConverter());
    }

    /**
     * 公钥验证
     */
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setVerifier(new RsaVerifier(this.getPubKey()));
        return converter;
    }

    /**
     * 获取本地公钥
     *
     * @return 返回公钥
     */
    private String getPubKey() {
        String            keyUri   = tokenProperties.getKeyUri();
        ClassPathResource resource = new ClassPathResource(keyUri);
        try (BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
            return br.lines().collect(Collectors.joining("\n"));
        } catch (IOException e) {
            log.warn("获取本地密钥出异常了：{}", e.getMessage());
            return getRemotePubKey();
        }
    }

    /**
     * 获取远程公钥
     *
     * @return 返回密钥
     */
    private String getRemotePubKey() {
        String keyUri = tokenProperties.getKeyUri();
        log.debug("联网公钥：{}", keyUri);

        Map map = new RestTemplate().getForObject(keyUri, Map.class);
        return map.get("value").toString();

    }


}
